﻿using System.Collections.Generic;
using System.Linq;

namespace Jeelu.Math
{
    /// <summary>最小公倍数
    /// </summary>
    public class LeaseCommonMultiple
    {
        private readonly List<long> _Array = new List<long>();

        public void AddToArray(params long[] items)
        {
            foreach (long item in items)
            {
                if (item <=0)
                    throw new JeeluMathException("最小公倍数是面向非零的自然数。");
                _Array.Add(item);
            }
            _Array.Sort();
        }

        public void ClearToArray()
        {
            _Array.Clear();
        }

        public bool RemoveToArray(long item)
        {
            return _Array.Remove(item);
        }

        public int CountOfArray
        {
            get { return _Array.Count; }
        }

        public bool ClongArray(IEnumerable<long> newArray)
        {
            _Array.Clear();
            AddToArray((long[]) newArray);
            return true;
        }

        public int IndexOfArray(long item)
        {
            return _Array.IndexOf(item);
        }

        public void InsertToArray(int index, long item)
        {
            if (item <= 0)
                throw new JeeluMathException("最小公倍数是面向非零的自然数。");

            _Array.Insert(index, item);
            _Array.Sort();
        }

        /// <summary>获取最小公倍数。
        /// 最小公倍数的范围一定是在数集中最大的数和所有数的积之间。
        /// </summary>
        public long GetLCM()
        {
            if (_Array.Count <= 1)
                throw new JeeluMathException("无必要对少于一个数求最小公倍数。");

            var tmpList = new long[_Array.Count];

            long max = _Array[_Array.Count-1];
            long allJi = _Array.Aggregate<long, long>(1, (current, item) => current*item);

            for (long lcm = max; lcm <= allJi; lcm++)
            {
                for (int i = 0; i < _Array.Count; i++)
                {
                    //将源数集合中的数对最小的数取余，并将取得的余数暂存在临时集合中
                    tmpList[i] = lcm % _Array[i];
                }
                if (IsZeroForAll(tmpList))
                {
                    //如果临时余数集合中所有数均为零，则已找到了最小公约数。
                    return lcm;
                }
            }
            return allJi;
        }

        private static bool IsZeroForAll(IEnumerable<long> array)
        {
            return array.All(t => t == 0);
        }

    }
}